package io.noties.markwon.plugin.typogram.parser

import io.noties.markwon.plugin.typogram.model.TypogramBlock
import org.commonmark.node.Block
import org.commonmark.parser.SourceLine
import org.commonmark.parser.block.AbstractBlockParser
import org.commonmark.parser.block.AbstractBlockParserFactory
import org.commonmark.parser.block.BlockContinue
import org.commonmark.parser.block.BlockStart
import org.commonmark.parser.block.MatchedBlockParser
import org.commonmark.parser.block.ParserState
import timber.log.Timber

/**
 * @since 4.3.0 (although it is just renamed parser from previous versions)
 */
internal class TypogramBlockParser : AbstractBlockParser() {
    private val block = TypogramBlock()
    private val builder = StringBuilder()
    private var isClosed = false

    override fun getBlock(): Block {
        return block
    }

    override fun tryContinue(parserState: ParserState): BlockContinue {
        return if (isClosed) {
            Timber.d("end typogram block text:${block.typogram}..")
            BlockContinue.finished()
        } else
            BlockContinue.atIndex(parserState.index)
    }

    override fun addLine(line: SourceLine) {
        line.content?.let {
            addLine(it)
        }
    }

    fun addLine(line: CharSequence) {
        if (builder.isNotEmpty()) {
            builder.append('\n')
        }
        builder.append(line)
        val length = builder.length
        if (length > 1) {
            isClosed = (SPLITER == builder[length - 1] && SPLITER == builder[length - 2])
            Timber.d("typogram block text:${builder}..")
            if (isClosed) {
                builder.replace(length - 2, length, "")
            }
        }
    }

    override fun closeBlock() {
        block.typogram=builder.toString()
    }

    companion object{
       const val SPLITER = '@'
    }

    class Factory : AbstractBlockParserFactory() {
        override fun tryStart(
            state: ParserState,
            matchedBlockParser: MatchedBlockParser
        ): BlockStart? {
            val line = state.line.content
            val length = line?.length ?: 0
            if (length > 1) {
                if (SPLITER == line!![0] && SPLITER == line[1]) {
                    Timber.d("Start typogram block text:$line..")
                    return BlockStart.of(TypogramBlockParser()).atIndex(state.index + 2)
                }
            }
            return null
        }
    }
}